#include <windows.h>
#include <Commctrl.h>
#include <stdio.h>

#include "resource.h"

BOOL TrayIcon( HWND, DWORD, wchar_t *, BOOL );
void TrayIconMainFunction( void );
void TrayIconContextMenu( HWND );

#define MAX_COUNT 1024

// global data definition and initialization
wchar_t g_wcCurrentSong[ MAX_COUNT ];
wchar_t g_wcCurrentArtist[ MAX_COUNT ];
HINSTANCE g_hInstance = NULL;
HWND g_hDlg = NULL;
HICON g_hSmallIcon = NULL;
BOOL g_fUse256ColorTrayIcon = FALSE;
UINT g_uiDoubleClickMode = 0;
UINT g_uiWM_TASKBARCREATED;

// our custom Windows message
#define WM_TRAYICONCLICK WM_APP + 100

// id of our icon in the tray area
#define TRAYICONID 0

// id of timer
#define IDT_TIMER 100

BOOL CALLBACK EnumWindowsProc(
  __in  HWND hwnd,
  __in  LPARAM lParam
)
{
	wchar_t windowText[ MAX_COUNT ];
	wchar_t className[ MAX_COUNT ];

	GetWindowText( hwnd, windowText, MAX_COUNT );
	GetClassName(hwnd, className, MAX_COUNT );

	if( lParam == 0 && ( wcscmp( className, L"IEFrame" ) == 0 || wcscmp( className, L"Chrome_WidgetWin_0" ) == 0 ) )
	{
		EnumChildWindows( hwnd, EnumWindowsProc, 1 );
	}

	if( lParam == 1 && ( wcscmp( className, L"TabWindowClass" ) == 0 || wcscmp( className, L"Chrome_WidgetWin_0" ) == 0 ) )
	{
		wchar_t *firstOccurrence = wcsstr( windowText, L"Music Beta" );
		if( firstOccurrence != NULL && firstOccurrence != windowText )
		{
			*firstOccurrence = 0;
			wcscpy_s( g_wcCurrentSong, MAX_COUNT, windowText );
									// modify the tooltip text 
						//TrayIcon( g_hDlg, NIM_MODIFY, windowText );
			//MessageBox( hwnd, windowText, className, MB_OK );
		}
	}

	return TRUE;
}

BOOL IsNewSongPlaying()
{
	wchar_t wcCurrentSong[ MAX_COUNT ];

	wcCurrentSong[ 0 ] = 0;

	wcscpy_s( wcCurrentSong, MAX_COUNT, g_wcCurrentSong );

	EnumWindows( EnumWindowsProc, 0 );

	return wcscmp( g_wcCurrentSong, wcCurrentSong );
}

/*
	TrayIcon -- Shell_NotifyIcon function wrapper

	Parameters
		HWND hwnd		: handle of the owner window
		DWORD dwMsg		: message (NIM_*)
		wchar_t *szTipText	: text for the tooltip, or NULL to maintain the existing

	Result
		BOOL			: TRUE if ok, FALSE otherwise
*/
BOOL TrayIcon( HWND hwnd, DWORD dwMsg, wchar_t *szTipText, BOOL fShowAsInfo )
{
	NOTIFYICONDATA nid;

	// destroy the small icon 
	if( g_hSmallIcon ) DestroyIcon( g_hSmallIcon );

	// load new small icon
	//g_hSmallIcon = ( HICON )LoadImage( g_hInstance, g_fUse256ColorTrayIcon ? MAKEINTRESOURCE( IDI_TRAYICON256 ) : MAKEINTRESOURCE( IDI_TRAYICON16 ), IMAGE_ICON, 16, 16, 0 );
	//g_hSmallIcon = LoadIcon( g_hInstance, MAKEINTRESOURCE( IDI_TRAYICON256 ) );
	g_hSmallIcon = ( HICON )LoadImage( g_hInstance, MAKEINTRESOURCE( IDI_TRAYICON256 ), IMAGE_ICON, 16, 16, 0 );

	// clear the structure
	ZeroMemory( &nid, sizeof( NOTIFYICONDATA ) );

	// initialize the structure
	nid.cbSize = sizeof( NOTIFYICONDATA );
	nid.uVersion =  NOTIFYICON_VERSION_4;
	nid.hWnd = hwnd;
	nid.uID = TRAYICONID;
	nid.uFlags = szTipText ? NIF_ICON|NIF_MESSAGE|NIF_TIP : NIF_ICON|NIF_MESSAGE;
	nid.uCallbackMessage = WM_TRAYICONCLICK;
	nid.hIcon = g_hSmallIcon;

	// check for tooltip text
	if( szTipText ) {
//		if( DLLVersion( "shell32.dll" ) < PACKVERSION( 5, 0) ) {
//			lstrcpyn( nid.szTip, szTipText, 64 );
//		} else {
			lstrcpyn( nid.szTip, szTipText, 128 );
//		}
	}

	if( fShowAsInfo )
	{
		nid.uFlags = NIF_INFO|NIF_ICON;
		nid.dwInfoFlags = NIIF_USER;
		
		int i = 0;
		int j = 0;
		while( szTipText[ i ] != '-' ) nid.szInfoTitle[ j++ ] = szTipText[ i++ ];
		nid.szInfoTitle[ --j ] = 0;
		j = 0; i += 2;
		while( szTipText[ i ] != '-' ) nid.szInfo[ j++ ] = szTipText[ i++ ];
		nid.szInfo[ --j ] = 0;
	}

	// call the API function
	return Shell_NotifyIcon( dwMsg, &nid );
}

/*
	TrayIconDlgProc -- dialog procedure

	Parameters
		HWND hDlg		: handle of the dialog window
		UINT Msg		: message
		WPARAM wParam	: W parameter
		LPARAM lParam	: L parameter

	Result
		LRESULT			: result of the message processing, depending on the message sent
*/
LRESULT TrayIconDlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam )
{
	//BOOL fShiftDown;
	wchar_t szTip[ 128 ];
	wchar_t szDoubleClick[ 32 ];

	// check the message
	switch( uiMsg ) {
	
		case WM_INITDIALOG:
//			SetPointer( GetDlgItem( hDlg, IDC_HYPERLINK ) );
			SetTimer( hDlg, IDT_TIMER, 1000, ( TIMERPROC )NULL );
//			g_uiWM_TASKBARCREATED = RegisterWindowMessage( L"TaskbarCreated" );			
			break;

		case WM_PAINT:
//			Redraw( GetDlgItem( hDlg, IDC_HYPERLINK ), blnVisited );
			break;

		case WM_CTLCOLORSTATIC:
//			if( ( HWND )lParam == GetDlgItem( hDlg, IDC_HYPERLINK ) ) {
//				return SetColors( GetDlgItem( hDlg, IDC_HYPERLINK ), ( HDC )wParam, blnVisited );
//			}
			break;
		
		case WM_TIMER:
			switch( wParam ) {
				case IDT_TIMER:
					if( IsNewSongPlaying() ) {
//						ScheduleExecute( g_hDlg );
						TrayIcon( g_hDlg, NIM_MODIFY, g_wcCurrentSong, true );
					}
					break;
			}
			break;

		// command
		case WM_COMMAND:

			// check for the id of a command
			switch( LOWORD( wParam ) ) {

				//case IDC_HYPERLINK:

				//	// set flag and invalidate control to force redraw
				//	blnVisited = TRUE;
				//	InvalidateRect( GetDlgItem( hDlg, IDC_HYPERLINK ), NULL, TRUE );

				//	// go to URL
				//	GotoURL( GetDlgItem( hDlg, IDC_HYPERLINK )  );

				//	break;

				case IDOK:
					TrayIconMainFunction();
					break;

				case IDCANCEL:
					PostQuitMessage( 0 );
					return 0;

				case ID_ABOUT:
					ShowWindow( g_hDlg, SW_SHOW );
					break;

				case ID_HIDE:
					ShowWindow( g_hDlg, SW_HIDE );
					break;

			}
			break;

		// click on the tray icon
		case WM_TRAYICONCLICK:

			// check the icon id
			if( wParam == TRAYICONID ) {

				// check the event
				switch( lParam ) {

					// right click on the tray icon
					case WM_RBUTTONUP:
						// display the context menu
						SetForegroundWindow( g_hDlg );
						TrayIconContextMenu( g_hDlg );
						SetForegroundWindow( g_hDlg );						
						break;

					// left double-click on the tray icon
					case WM_LBUTTONDBLCLK:
						TrayIconMainFunction();
						break;

					// mouse move over tray icon
					case WM_MOUSEMOVE:
						
						// get double click function message
						if( g_uiDoubleClickMode == 0 ) {
							swprintf( szDoubleClick, 32, L"%s", L"Double-click disabled" );
						} else {
							if( g_uiDoubleClickMode == 1 ) swprintf( szDoubleClick, 32, L"%s", L"Double-click to restart" );
							if( g_uiDoubleClickMode == 2 ) swprintf( szDoubleClick, 32, L"%s", L"Double-click to shutdown" );
							if( g_uiDoubleClickMode == 3 ) swprintf( szDoubleClick, 32, L"%s", L"Double-click to edit schedule" );
						}

						// build tooltip
						//swprintf( szTip, 128, g_fUse256ColorTrayIcon ? L"%s\n%s" : L"%s (%s)", BootGetInstalledNumber() != 0 ? BootGetDefaultName() : MESSAGE_NOOSFOUND, szDoubleClick ); 
						swprintf( szTip, 128, L"%s", g_wcCurrentSong );

						// modify the tooltip text 
						TrayIcon( g_hDlg, NIM_MODIFY, szTip, false );

						break;

				}
			}
	
		default:

			// check for TaskbarCreated message
			if( uiMsg == g_uiWM_TASKBARCREATED ) {

				// delete and add tray icon
				TrayIcon( g_hDlg, NIM_DELETE, NULL, false );
				TrayIcon( g_hDlg, NIM_ADD, L"Inizializing...", false );

			}
			
	}

	return 0;
}

/*
	TrayIconContextMenu -- display the context menu

	Parameters
		HWND hwnd	: handle of the window
*/
void TrayIconContextMenu( HWND hwnd )
{
	HMENU hmenu, hmnuPopup;
	POINT pt;
	//size_t i;

	// get the current mouse position
	GetCursorPos( &pt );

	// load the menu from the resources, getting the first popup menu
	hmenu = LoadMenu( g_hInstance, MAKEINTRESOURCE( IDR_MENU ) );	
	hmnuPopup = GetSubMenu( hmenu, 0 );

	// display the menu
	TrackPopupMenu( hmnuPopup, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL );
	
	// destroy the loaded menu resources
	DestroyMenu( hmnuPopup );
	DestroyMenu( hmenu );
}

/*
	TrayIconMainFunction -- execute the main function of the program
*/
void TrayIconMainFunction()
{
}

void SetupNotifyIcon()
{
	// create the dialog from the resources
	g_hDlg = CreateDialog( g_hInstance, MAKEINTRESOURCE( IDD_DIALOG ), NULL, ( DLGPROC ) TrayIconDlgProc );
	
	//ShowWindow( g_hDlg, SW_SHOW );

	// add the icon to the tray area
	TrayIcon( g_hDlg, NIM_ADD, L"Initializing...", false );
}

int CALLBACK WinMain(
  __in  HINSTANCE hInstance,
  __in  HINSTANCE hPrevInstance,
  __in  LPSTR lpCmdLine,
  __in  int nCmdShow
)
{
	MSG msg;

	// save the current instance handle
	g_hInstance = hInstance;

	// load the small icon from the resources
	g_hSmallIcon = ( HICON )LoadImage( g_hInstance, MAKEINTRESOURCE( IDI_TRAYICON256 ), IMAGE_ICON, 16, 16, 0 );

	//LoadIconMetric( g_hInstance, MAKEINTRESOURCE( IDI_TRAYICON256 ), LIM_SMALL, &g_hSmallIcon );

	SetupNotifyIcon();
	//EnumWindows( EnumWindowsProc, 0 );

	// add the icon to the tray area
	TrayIcon( g_hDlg, NIM_ADD, L"Initializing...", false );

	// process messages
	while ( GetMessage( &msg, ( HWND )NULL, 0, 0 ) ) {
		if ( !IsDialogMessage( g_hDlg, &msg ) ) {
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}

	// remove the icon from the tray area
	TrayIcon( g_hDlg, NIM_DELETE, NULL, false );

	// destroy timer
	KillTimer( g_hDlg, IDT_TIMER );

	// destroy the dialog window
	DestroyWindow( g_hDlg );

	// destroy the small icon 
	DestroyIcon( g_hSmallIcon );

	// return the result code
	return ( int )msg.wParam;
}